package com.globalwave.common.task;

import java.sql.Timestamp;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.globalwave.common.cache.CodeHelper;
import com.globalwave.common.entity.SyncControl;
import com.globalwave.common.scheduling.RunnableTask;
import com.globalwave.common.service.SyncControlService;
import com.globalwave.datasync.SyncConfig;
import com.globalwave.datasync.SyncContext;
import com.globalwave.datasync.engine.BaseSync;
import com.globalwave.datasync.engine.IncrementInsertSync;
import com.globalwave.datasync.engine.MoveSync;

public class SyncControlTask extends RunnableTask {

	protected Log log = LogFactory.getLog(this.getClass()) ;
	
	private SyncControlService syncControlService ;
	
	protected String sourceDbCode = null ;// 
	protected String syncConfigCode = null ;
	
	public void execute() throws Exception {
		
		if (sourceDbCode == null) {
			sourceDbCode = (String)super.getContext().get("sourceDbCode") ;
			syncConfigCode = (String)super.getContext().get("syncConfigCode") ;
		}
		syncControlService = (SyncControlService)CodeHelper.getAppContext().getBean("syncControlService");
		SyncControl control = syncControlService.findByCodeAndTable(sourceDbCode, syncConfigCode) ;
		//new SyncControl() ;// #control=bo.findByCodeAndTable(dbCode, dbTableName) ;
		if (control == null) {
			control = new SyncControl() ;
			control.setCurrentLongId(new Long(0)) ;
			control.setSourceDbCode(sourceDbCode) ;
			control.setSyncConfigCode(syncConfigCode) ;
			control.setErrorTimes(new Integer(0)) ;
			control.setStartOn(new Timestamp(System.currentTimeMillis())) ;
			control.setStatus(SyncControl.STATUS_RUNNING) ;
			syncControlService.create(control) ;
		} else {
			if (SyncControl.STATUS_RUNNING.equals(control.getStatus())) {
				log.error("another sync thread is running,this thread is terminated!") ;
				return ;
			} /*else if (SyncControl.STATUS_FAIL.equals(control.getStatus())) {
				log.error("the preview thread was not executed successfully, this thread is terminated!") ;
				return ;
			}*/
			control.setStartOn(new Timestamp(System.currentTimeMillis())) ;
			control.setEndOn(null) ;
			control.setStatus(SyncControl.STATUS_RUNNING) ;
			syncControlService.update(control) ;
		}

		SyncContext context = new SyncContext() ;
		Long start = control.getCurrentLongId() ;
		context.put("start", start) ;
		BaseSync sync = null ;
		if (SyncConfig.MODE_INCREMENT_INSERT.equals(super.getContext().get("SYNC_MODE"))) {
			sync = new IncrementInsertSync(sourceDbCode, syncConfigCode, connectionProvider) ;
		} else {
			sync = new MoveSync(sourceDbCode, syncConfigCode, connectionProvider) ;
		}
		try {
			while (start != null) {
			    sync.execute(context) ;
			    
			    Long end = (Long)context.get("end") ;
			    if (end != null) {
			    	end ++ ;// result deal
			    	control.setCurrentLongId(end) ;
			    	// #bo.update(control);
					syncControlService.update(control) ;
			    	
			    	context.remove("end") ;// prepare next loop
			    	if(isCanceled()) {
			    		start = null ;
			    	} else {
				    	start = end ;
				    	context.put("start", start) ;
			    	}
			    } else {
			    	start = null ;// no data process, loop end
			    }
			}

			control.setStatus(SyncControl.STATUS_SUCCESS) ;
			control.setEndOn(new Timestamp(System.currentTimeMillis())) ;
			syncControlService.update(control) ;
		} catch(Exception e) {
			//e.printStackTrace() ;
			log.error("SyncControlTask - ", e) ;
	    	control.setErrorTimes(
	    			control.getErrorTimes() == null? 
	    					1: control.getErrorTimes() + 1) ;
			
	    	// #bo.update(control);
	    	control.setStatus(SyncControl.STATUS_FAIL) ;
			syncControlService.update(control) ;
		}
	}

	public void setSyncControlService(SyncControlService syncControlService) {
		this.syncControlService = syncControlService;
	}
	
}
